/*
 * ========================================
 * 内存管理接口定义
 * ========================================
 * 
 * 这个文件定义了内存管理系统的公共接口，包括：
 * - 物理内存分配器接口
 * - 虚拟内存管理接口
 * - 页表操作接口
 */

#ifndef MEMORY_H
#define MEMORY_H

#include "types.h"
#include "riscv.h"

// ========================================
// 物理内存分配器接口
// ========================================

/*
 * 分配一个物理页面
 * @return 物理地址，失败返回0
 */
void* kalloc(void);

/*
 * 释放一个物理页面
 * @param pa 物理地址
 */
void kfree(void *pa);

/*
 * 初始化物理内存分配器
 */
void kalloc_init(void);

/*
 * 获取内存分配统计信息
 * @param total 总页面数
 * @param free 空闲页面数
 * @param allocated 已分配页面数
 */
void kalloc_stats(uint64 *total, uint64 *free, uint64 *allocated);

/*
 * 打印内存分配统计信息
 */
void kalloc_print_stats(void);

// ========================================
// 虚拟内存管理接口
// ========================================

/*
 * 初始化虚拟内存系统
 */
void vm_init(void);

/*
 * 启用虚拟内存
 */
void vm_enable(void);

/*
 * 获取内核页表
 * @return 内核页表指针
 */
pagetable_t get_kernel_pagetable(void);

/*
 * 打印虚拟内存统计信息
 */
void vm_print_stats(void);

/*
 * 测试虚拟内存功能
 */
void vm_test(void);

// ========================================
// 页表操作接口
// ========================================

/*
 * 查找页表项
 * @param pagetable 页表指针
 * @param va 虚拟地址
 * @param alloc 如果页表不存在是否分配
 * @return 页表项指针
 */
pte_t* walk(pagetable_t pagetable, uint64 va, int alloc);

/*
 * 映射页面
 * @param pagetable 页表指针
 * @param va 虚拟地址
 * @param size 大小
 * @param pa 物理地址
 * @param perm 权限
 * @return 成功返回0，失败返回-1
 */
int mappages(pagetable_t pagetable, uint64 va, uint64 size, uint64 pa, int perm);

/*
 * 取消映射
 * @param pagetable 页表指针
 * @param va 虚拟地址
 * @param size 大小
 */
void unmappages(pagetable_t pagetable, uint64 va, uint64 size);

// ========================================
// 内存工具函数
// ========================================

/*
 * 内存复制
 * @param dst 目标地址
 * @param src 源地址
 * @param n 字节数
 * @return 目标地址
 */
void* memcpy(void *dst, const void *src, uint64 n);

/*
 * 内存设置
 * @param dst 目标地址
 * @param c 要设置的字节值
 * @param n 字节数
 * @return 目标地址
 */
void* memset(void *dst, int c, uint64 n);

/*
 * 内存比较
 * @param s1 字符串1
 * @param s2 字符串2
 * @param n 字节数
 * @return 相等返回0，否则返回差值
 */
int memcmp(const void *s1, const void *s2, uint64 n);

// ========================================
// 地址转换宏
// ========================================

// 虚拟地址到物理地址转换
#define VA2PA(va)       (PTE2PA(*walk(get_kernel_pagetable(), (va), 0)))

// 物理地址到虚拟地址转换（简化版）
#define PA2VA(pa)       ((pa))

// ========================================
// 内存管理常量
// ========================================

// 内存分配器状态
#define KALLOC_INIT     0   // 未初始化
#define KALLOC_READY    1   // 已初始化
#define KALLOC_ERROR    2   // 错误状态

// 页表权限组合
#define PTE_RWX         (PTE_R | PTE_W | PTE_X)  // 读、写、执行
#define PTE_RW          (PTE_R | PTE_W)          // 读、写
#define PTE_RX          (PTE_R | PTE_X)          // 读、执行
#define PTE_READ_ONLY   (PTE_R)                  // 只读

#endif // MEMORY_H
